package session

import (
	"github.com/cz-it/golangutils/log"
	"github.com/cz-it/gonnectd/src/config"

	"container/list"
	"fmt"
	"sync"
)

type SessionID uint32

type SessionPool struct {
	Mtx sync.Mutex

	Pool []Session
	Idle *list.List
	Cap  SessionID
}

var pool *SessionPool

func Init() error {
	var err error
	pool, err = NewSessionPool(config.SessionPoolSize)
	if err != nil {
		log.Error("Create Session Pool Failed!")
		fmt.Println("Create Session Pool Failed!")
		return err
	}
	return nil
}

func Create() (SessionID, error) {
	pool.Mtx.Lock()
	id := pool.Idle.Front()
	pool.Idle.Remove(id)
	pool.Mtx.Unlock()
	return id.Value.(SessionID), nil
}

func Release(id SessionID) {
	pool.Mtx.Lock()
	pool.Idle.PushBack(id)
	pool.Pool[id].Init()
	pool.Mtx.Unlock()
}

func NewSessionPool(size uint32) (*SessionPool, error) {
	sessionPool := new(SessionPool)
	sessionPool.Pool = make([]Session, size)
	sessionPool.Cap = SessionID(size)
	sessionPool.Idle = list.New()

	for i := SessionID(0); i < sessionPool.Cap; i++ {
		sessionPool.Pool[i].Init()
		sessionPool.Idle.PushBack(i)
	}
	return sessionPool, nil
}
